package org.ala.everyday;

/**
 * 给你一个下标从 0 开始的字符串 text 和另一个下标从 0 开始且长度为 2 的字符串 pattern ，两者都只包含小写英文字母。
 *
 * 你可以在 text 中任意位置插入 一个 字符，这个插入的字符必须是 pattern[0] 或者 pattern[1] 。注意，这个字符可以插入在 text 开头或者结尾的位置。
 *
 * 请你返回插入一个字符后，text 中最多包含多少个等于 pattern 的 子序列 。
 *
 * 子序列 指的是将一个字符串删除若干个字符后（也可以不删除），剩余字符保持原本顺序得到的字符串。
 *
 *
 *
 * 示例 1：
 *
 * 输入：text = "abdcdbc", pattern = "ac"
 * 输出：4
 * 解释：
 * 如果我们在 text[1] 和 text[2] 之间添加 pattern[0] = 'a' ，那么我们得到 "abadcdbc" 。那么 "ac" 作为子序列出现 4 次。
 * 其他得到 4 个 "ac" 子序列的方案还有 "aabdcdbc" 和 "abdacdbc" 。
 * 但是，"abdcadbc" ，"abdccdbc" 和 "abdcdbcc" 这些字符串虽然是可行的插入方案，但是只出现了 3 次 "ac" 子序列，所以不是最优解。
 * 可以证明插入一个字符后，无法得到超过 4 个 "ac" 子序列。
 * 示例 2：
 *
 * 输入：text = "aabb", pattern = "ab"
 * 输出：6
 * 解释：
 * 可以得到 6 个 "ab" 子序列的部分方案为 "aaabb" ，"aaabb" 和 "aabbb" 。
 *
 *
 * 提示：
 *
 * 1 <= text.length <= 105
 * pattern.length == 2
 * text 和 pattern 都只包含小写英文字母。
 *
 * @author ala
 * @date 2024-09-24 00:45
 */
public class Q2207 {

    public static void main(String[] args) {
        Q2207 q = new Q2207();

//        String text = "abdcdbc",
//               pattern = "ac";

//        String text = "aabb",
//               pattern = "ab";

//        String text = "iekbksdsmuuzwxbpmcngsfkjvpzuknqguzvzik",
//                pattern = "mp";

        String text = "iuvgbmteyivbfwuospxmmgzagfa",
                pattern = "ti";

        System.out.println(q.maximumSubsequenceCount(text, pattern));
    }

    public long maximumSubsequenceCount(String text, String pattern) {
        return V1(text, pattern);
    }
    /**
     *  1）pattern的长度只有2，所以假设pattern的字母是a和b
     *  2）假设第i个位置，前面有m个a，后面有n个b，那第i个位置就有 m * n 个子序列
     *      (m + 1) * n 和 m * (n + 1) 取大即可
     *  3）统计每个a，前面有多少个a（含自己），后面有多少个b
     *      从左往右，遇到a，写入个数并记下下标
     *      从右往左，遇到b：写入个数并
     *              遇到a：把之前记录的个数写入该下标，并计算(m + 1) * n 和 m * (n + 1)，过程中取大
     *              如果此时b的数量没有变化，则忽略该下标
     *  4）特判：
     *      1. 如果 a == b，则：∑m就是答案（m + 1）个a能组合出的aa数量
     *      2. 如果 m == 0 或 n == 0，则：m + 1 或 n + 1 取大即为答案
     */
    protected long V1(String text, String pattern) {
        char[] cs = text.toCharArray(),
                ps = pattern.toCharArray();
        int N = cs.length;

        char a = ps[0], b = ps[1];
        //  从左往右，统计每个 a 前面（含自己）a的数量
        long[] acnt = new long[N];
        int pa = -1;
        long acrt = 0;
        for (int i = 0 ; i < N ; i++) {
            char c = cs[i];
            if (c == a) {
                acnt[++pa] = ++acrt;
            }
        }

        //  特判：
        //  如果 a == b，则 crt * (crt + 1) / 2 就是答案（m+1个a，可以凑出的aa）
        if (a == b) { return acrt * (acrt + 1) / 2; }

        //  从右往左，统计每个a右边b的数量
        long bcrt = 0l, res = 0l, incr = 0l;
        for (int i = N - 1 ; i >= 0 ; i--) {
            char c = cs[i];
            if (c == b) {
                bcrt++;
            } else if (c == a) {
                //  在该位置插入a或b，会让结果多了一个ca，或多了一个bcrt。记录下当前最大的增益
                long ca = acnt[pa--];
                res += bcrt;
                incr = Math.max(incr, Math.max(ca, bcrt));
            }
        }

        //  如果a,b的数量都是0，那遇到老6了，直接返回0
        if (acrt == 0 && bcrt == 0) { return 0l; }
        //  如果 a == 0，那 b + 1 就是答案
        else if (acrt == 0) { return bcrt; }
        else if (bcrt == 0) { return acrt; }
        else {
            //  在中间补b，和最左边补b，和最左边补a，三者取大
            return Math.max(res + incr, Math.max(res + bcrt, res + acrt));
        }
    }
}
